#ifndef VERTEX_H_INCLUDED
#define VERTEX_H_INCLUDED

#include "Vector.h"

// Bit-map of vertex properties
#define NIL 0
#define POS 1
#define COL 2
#define NOR 4
#define TEX 8
#define IDX16 16
#define IDX32 32

/// Structure to hold the full vertex information
struct tzmVertex {
   float   x,y,z;			///< Vertex coordinates
   float   nx,ny,nz;		///< Vertex normal
   float   u,v;			///< Vertex texture coordinates
   ulong	  color;			///< Vertex color

	tzmVertex( ) : x(0), y(0), z(0), nx(0), ny(0), nz(0), u(0), v(0), color(0) { }
	tzmVertex( float xx, float yy = 0, float zz = 0, float nnx = 0, float nny = 0, float nnz = 0, float uu = 0, float vv = 0, ulong col = 0 ) : x(xx), y(yy), z(zz), nx(nnx), ny(nny), nz(nnz), u(uu), v(vv), color(col) { }
	tzmVertex( cvec3r &pos, cvec3r &nor, cvec2r &uv, crgba &col ) : x(pos.x), y(pos.y), z(pos.z), nx(nor.x), ny(nor.y), nz(nor.z), u(uv.x), v(uv.y), color( col.ULong( ) ) { }
};

/// Structure to hold the vertex position, normal and texture coordinates
#pragma pack(push, 1)
struct tzmVertexPNT {
   float   x,y,z;			///< Vertex coordinates
   float   nx,ny,nz;		///< Vertex normal
   float   u,v;			///< Vertex texture coordinates

	tzmVertexPNT( ) : x(0), y(0), z(0), nx(0), ny(0), nz(0), u(0), v(0) { }
	tzmVertexPNT( float xx, float yy, float zz, float nnx, float nny, float nnz, float uu, float vv ) : x(xx), y(yy), z(zz), nx(nnx), ny(nny), nz(nnz), u(uu), v(vv) { }
	tzmVertexPNT( cvec3r &pos, cvec3r &nor, cvec2r &uv ) : x(pos.x), y(pos.y), z(pos.z), nx(nor.x), ny(nor.y), nz(nor.z), u(uv.x), v(uv.y) { }
};
#pragma pack(pop)

/// Structure to hold the vertex position, color and texture coordinates
struct tzmVertexPCT {
   float   x,y,z;			///< Vertex coordinates
	ulong	  color;			///< Vertex color
   float   u,v;			///< Vertex texture coordinates

	tzmVertexPCT( ) : x(0), y(0), z(0), color(0), u(0), v(0) { }
	tzmVertexPCT( float xx, float yy, float zz, float uu, float vv, ulong col ) : x(xx), y(yy), z(zz), color(col), u(uu), v(vv) { }
	tzmVertexPCT( cvec3r &pos, cvec2r &uv, crgba &col ) : x(pos.x), y(pos.y), z(pos.z), color(col.ULong()), u(uv.x), v(uv.y) { }
};

/// Structure to hold the vertex position, normal and color coordinates
struct tzmVertexPNC {
   float x,y,z;			///< Vertex coordinates
   float nx,ny,nz;		///< Vertex normal
   ulong	color;			///< Vertex color

	tzmVertexPNC( ) : x(0), y(0), z(0), nx(0), ny(0), nz(0), color(0) { }
	tzmVertexPNC( float xx, float yy, float zz, float nnx, float nny, float nnz, ulong col ) : x(xx), y(yy), z(zz), nx(nnx), ny(nny), nz(nnz), color(col) {}
	tzmVertexPNC( cvec3r &pos, cvec3r &nor, crgba &col ) : x(pos.x), y(pos.y), z(pos.z), nx(nor.x), ny(nor.y), nz(nor.z), color(col.ULong()) {}
};

/// Structure to hold the vertex position and normal
struct tzmVertexPN {
   float x,y,z;			///< Vertex coordinates
   float nx,ny,nz;		///< Vertex normal

	tzmVertexPN( ) : x(0), y(0), z(0), nx(0), ny(0), nz(0) { }
	tzmVertexPN( float xx, float yy, float zz, float nnx, float nny, float nnz ) : x(xx), y(yy), z(zz), nx(nnx), ny(nny), nz(nnz) { }
	tzmVertexPN( cvec3r &pos, cvec3r &nor ) : x(pos.x), y(pos.y), z(pos.z), nx(nor.x), ny(nor.y), nz(nor.z) { }
};

/// Structure to hold the vertex position and color
struct tzmVertexPC{
   float x,y,z;			///< Vertex coordinates
	ulong	color;			///< Vertex color

	tzmVertexPC( ) : x(0), y(0), z(0), color(0) { }
	tzmVertexPC( float xx, float yy, float zz, ulong col ) : x(xx), y(yy), z(zz), color(col) { }
	tzmVertexPC( cvec3r &pos, crgba &col ) : x(pos.x), y(pos.y), z(pos.z), color(col.ULong()) { }
};

/// Structure to hold the vertex position and texture coordinates
struct tzmVertexPT{
   float x,y,z;			///< Vertex coordinates
   float u,v;				///< Vertex texture coordinates

	tzmVertexPT( ) : x(0), y(0), z(0), u(0), v(0) { }
	tzmVertexPT( float xx, float yy, float zz, float uu, float vv ) : x(xx), y(yy), z(zz), u(uu), v(vv) { }
	tzmVertexPT( cvec3r &pos, float uu, float vv ) : x(pos.x), y(pos.y), z(pos.z), u(uu), v(vv) { }
	tzmVertexPT( cvec3r &pos, cvec2r &uv ) : x(pos.x), y(pos.y), z(pos.z), u(uv.x), v(uv.y) { }
};

/// Structure to hold 3 float
#pragma pack(push, 1)
struct tzmVertexP{
   float   x,y,z;			///< Vertex coordinates

	tzmVertexP( ) : x(0), y(0), z(0) { }
	tzmVertexP( float xx, float yy, float zz ) : x(xx), y(yy), z(zz) { }
	tzmVertexP( cvec3r &point ) : x((float)point.x), y((float)point.y), z((float)point.z) { }
};
#pragma pack(pop)

/// ENUM for the Data type in the buffer
enum VERTEX_PRIMITIVE_TYPE {
	VPT_INVALID = 0,
   VPT_UNKNOWN,
   VPT_LINES,
	VPT_LINE_STRIP,
	VPT_LINE_LOOP,
   VPT_POINTS,
   VPT_TRIANGLES,
   VPT_TRI_STRIP,
   VPT_TRI_FAN,
   VPT_QUADS,
   VPT_QUAD_STRIP,
   VPT_POLYGON,
	VPT_INSTANCE_DATA
};

/// ENUM for byte offsets
enum VBUFFER_OFFSETS {
	VO_POS = 0,
	VO_COL,
	VO_NOR,
	VO_TEX
};

#define OFFSET( val ) ((char*)NULL + (val))

#endif // VERTEX_H_INCLUDED
